#ifndef _VECTOR3_H
#define _VECTOR3_H

#include "Common.h"

#include <cmath>

namespace Pandora
{

	class CVector3
	{
	public:
		CVector3() : x( 0.0f ), y( 0.0f ), z( 0.0f ) {};
		CVector3( float a_X, float a_Y, float a_Z ) : x( a_X ), y( a_Y ), z( a_Z ) {};

		void Set( float a_X, float a_Y, float a_Z ) { x = a_X; y = a_Y; z = a_Z; }
		void Normalize() { float l = 1.0f / Length(); x *= l; y *= l; z *= l; }
		float Length() { return sqrtf( x * x + y * y + z * z ); }
		float SqrLength() { return x * x + y * y + z * z; }
		float Dot( CVector3& a_V ) { return x * a_V.x + y * a_V.y + z * a_V.z; }
		CVector3 Cross( CVector3& b ) { return CVector3( y * b.z - z * b.y, z * b.x - x * b.z, x * b.y - y * b.x ); }
		float Dot( CVector3* a_V ) { return x * a_V->x + y * a_V->y + z * a_V->z; }
		CVector3* Cross( CVector3* b ) { return new CVector3( y * b->z - z * b->y, z * b->x - x * b->z, x * b->y - y * b->x ); }

		CVector3* Add(CVector3* v) { return new CVector3(x + v->x, y + v->y, z + v->z); }
		CVector3* Substract(CVector3* v) { return new CVector3(x - v->x, y - v->y, z - v->z); }
		CVector3* Multiply(CVector3* v) { return new CVector3(x * v->x, y * v->y, z * v->z); }
		CVector3* DivideBy(CVector3* v) { return new CVector3(x / v->x, y / v->y, z / v->z); }

		void operator += ( CVector3& a_V ) { x += a_V.x; y += a_V.y; z += a_V.z; }
		void operator += ( CVector3* a_V ) { x += a_V->x; y += a_V->y; z += a_V->z; }
		void operator -= ( CVector3& a_V ) { x -= a_V.x; y -= a_V.y; z -= a_V.z; }
		void operator -= ( CVector3* a_V ) { x -= a_V->x; y -= a_V->y; z -= a_V->z; }
		void operator *= ( float f ) { x *= f; y *= f; z *= f; }
		void operator *= ( CVector3& a_V ) { x *= a_V.x; y *= a_V.y; z *= a_V.z; }
		void operator *= ( CVector3* a_V ) { x *= a_V->x; y *= a_V->y; z *= a_V->z; }
		CVector3 operator- () const { return CVector3( -x, -y, -z ); }
		friend CVector3 operator + ( const CVector3& v1, const CVector3& v2 ) { return CVector3( v1.x + v2.x, v1.y + v2.y, v1.z + v2.z ); }
		friend CVector3 operator - ( const CVector3& v1, const CVector3& v2 ) { return CVector3( v1.x - v2.x, v1.y - v2.y, v1.z - v2.z ); }
		friend CVector3 operator + ( const CVector3& v1, CVector3* v2 ) { return CVector3( v1.x + v2->x, v1.y + v2->y, v1.z + v2->z ); }
		friend CVector3 operator - ( const CVector3& v1, CVector3* v2 ) { return CVector3( v1.x - v2->x, v1.y - v2->y, v1.z - v2->z ); }
		friend CVector3 operator * ( const CVector3& v, float f ) { return CVector3( v.x * f, v.y * f, v.z * f ); }
		friend CVector3 operator * ( const CVector3& v1, CVector3& v2 ) { return CVector3( v1.x * v2.x, v1.y * v2.y, v1.z * v2.z ); }
		friend CVector3 operator * ( float f, const CVector3& v ) { return CVector3( v.x * f, v.y * f, v.z * f ); }
		friend CVector3 operator / ( const CVector3& v, float f ) { return CVector3( v.x / f, v.y / f, v.z / f ); }
		friend CVector3 operator / ( const CVector3& v1, CVector3& v2 ) { return CVector3( v1.x / v2.x, v1.y / v2.y, v1.z / v2.z ); }
		friend CVector3 operator / ( float f, const CVector3& v ) { return CVector3( v.x / f, v.y / f, v.z / f ); }

		union
		{
			struct { float x, y, z; };
			struct { float r, g, b; };
		};
	};

}; //namespace Pandora

#endif /* _VECTOR3_H */